/**
 * 拖拽操作封装类
 * 支持在固定范围内拖拽元素
 */
class DragHelper {
  constructor(element, options = {}) {
    this.element = element;
    this.options = {
      // 拖拽范围限制
      boundary: {
        left: 0,
        top: 0,
        right: window.innerWidth,
        bottom: window.innerHeight
      },
      // 是否启用拖拽
      enabled: true,
      // 拖拽开始时的回调
      onStart: null,
      // 拖拽过程中的回调
      onMove: null,
      // 拖拽结束时的回调
      onEnd: null,
      // 是否限制在父元素内
      constrainToParent: true,
      // 拖拽手柄选择器（可选）
      handle: null,
      // 初始位置 {x: number, y: number} 或 'center' 或 'random'
      initialPosition: null,
      ...options
    };
    
    this.isDragging = false;
    this.startX = 0;
    this.startY = 0;
    this.initialX = 0;
    this.initialY = 0;
    
    this.init();
  }
  
  init() {
    if (!this.element) {
      throw new Error('拖拽元素不能为空');
    }
    
    // 设置元素样式
    this.element.style.position = 'absolute';
    this.element.style.cursor = 'move';
    this.element.style.userSelect = 'none';
    
    // 获取拖拽手柄
    this.handle = this.options.handle ? 
      this.element.querySelector(this.options.handle) : 
      this.element;
    
    // 设置初始位置
    this.setInitialPosition();
    
    // 绑定事件
    this.bindEvents();
  }
  
  bindEvents() {
    this.handle.addEventListener('mousedown', this.onMouseDown.bind(this));
    document.addEventListener('mousemove', this.onMouseMove.bind(this));
    document.addEventListener('mouseup', this.onMouseUp.bind(this));
    
    // 触摸事件支持
    this.handle.addEventListener('touchstart', this.onTouchStart.bind(this), { passive: false });
    document.addEventListener('touchmove', this.onTouchMove.bind(this), { passive: false });
    document.addEventListener('touchend', this.onTouchEnd.bind(this));
  }
  
  onMouseDown(e) {
    if (!this.options.enabled) return;
    
    e.preventDefault();
    this.startDrag(e.clientX, e.clientY);
  }
  
  onTouchStart(e) {
    if (!this.options.enabled) return;
    
    e.preventDefault();
    const touch = e.touches[0];
    this.startDrag(touch.clientX, touch.clientY);
  }
  
  startDrag(clientX, clientY) {
    this.isDragging = true;
    this.startX = clientX;
    this.startY = clientY;
    
    // 获取元素当前位置（相对于父元素）
    const rect = this.element.getBoundingClientRect();
    const parentRect = this.element.parentElement ? this.element.parentElement.getBoundingClientRect() : { left: 0, top: 0 };
    this.initialX = rect.left - parentRect.left;
    this.initialY = rect.top - parentRect.top;
    
    
    // 触发开始回调
    if (this.options.onStart) {
      this.options.onStart({
        element: this.element,
        x: this.initialX,
        y: this.initialY
      });
    }
  }
  
  onMouseMove(e) {
    if (!this.isDragging) return;
    
    e.preventDefault();
    this.updateDrag(e.clientX, e.clientY);
  }
  
  onTouchMove(e) {
    if (!this.isDragging) return;
    
    e.preventDefault();
    const touch = e.touches[0];
    this.updateDrag(touch.clientX, touch.clientY);
  }
  
  updateDrag(clientX, clientY) {
    if (!this.isDragging) return;
    
    const deltaX = clientX - this.startX;
    const deltaY = clientY - this.startY;
    
    let newX = this.initialX + deltaX;
    let newY = this.initialY + deltaY;
    
    // 应用边界限制
    const boundary = this.getBoundary();
    
    // 确保元素不会超出边界
    newX = Math.max(boundary.left, Math.min(boundary.right, newX));
    newY = Math.max(boundary.top, Math.min(boundary.bottom, newY));
    
    // 更新元素位置
    this.element.style.left = newX + 'px';
    this.element.style.top = newY + 'px';
    
    // 触发移动回调
    if (this.options.onMove) {
      this.options.onMove({
        element: this.element,
        x: newX,
        y: newY,
        deltaX,
        deltaY
      });
    }
  }
  
  onMouseUp(e) {
    if (!this.isDragging) return;
    
    this.endDrag();
  }
  
  onTouchEnd(e) {
    if (!this.isDragging) return;
    
    this.endDrag();
  }
  
  endDrag() {
    this.isDragging = false;
    
    // 触发结束回调
    if (this.options.onEnd) {
      const rect = this.element.getBoundingClientRect();
      this.options.onEnd({
        element: this.element,
        x: rect.left,
        y: rect.top
      });
    }
  }
  
  getBoundary() {
    let boundary = { ...this.options.boundary };
    
    // 如果限制在父元素内
    if (this.options.constrainToParent && this.element.parentElement) {
      const parent = this.element.parentElement;
      
      // 获取容器的实际内容区域（包括边框和padding）
      const parentRect = parent.getBoundingClientRect();
      const parentStyle = window.getComputedStyle(parent);
      
      // 获取边框宽度
      const borderLeft = parseFloat(parentStyle.borderLeftWidth) || 0;
      const borderRight = parseFloat(parentStyle.borderRightWidth) || 0;
      const borderTop = parseFloat(parentStyle.borderTopWidth) || 0;
      const borderBottom = parseFloat(parentStyle.borderBottomWidth) || 0;
      
      // 获取padding
      const paddingLeft = parseFloat(parentStyle.paddingLeft) || 0;
      const paddingRight = parseFloat(parentStyle.paddingRight) || 0;
      const paddingTop = parseFloat(parentStyle.paddingTop) || 0;
      const paddingBottom = parseFloat(parentStyle.paddingBottom) || 0;
      
      // 计算实际可用的内容区域
      const availableWidth = parentRect.width - borderLeft - borderRight - paddingLeft - paddingRight;
      const availableHeight = parentRect.height - borderTop - borderBottom - paddingTop - paddingBottom;
      
      // 获取元素尺寸
      const elementWidth = this.element.offsetWidth;
      const elementHeight = this.element.offsetHeight;
      
      // 计算元素可以移动的最大位置
      // 右边界 = 可用宽度 - 元素宽度
      // 下边界 = 可用高度 - 元素高度
      const maxRight = Math.max(0, availableWidth - elementWidth);
      const maxBottom = Math.max(0, availableHeight - elementHeight);
      
      boundary = {
        left: 0,
        top: 0,
        right: maxRight,
        bottom: maxBottom
      };
    }
    
    return boundary;
  }
  
  // 设置初始位置
  setInitialPosition() {
    if (!this.options.initialPosition) {
      // 如果没有指定初始位置，保持当前位置
      this.updatePosition();
      return;
    }
    
    const boundary = this.getBoundary();
    let x, y;
    
    if (this.options.initialPosition === 'center') {
      // 居中显示
      const elementWidth = this.element.offsetWidth;
      const elementHeight = this.element.offsetHeight;
      x = (boundary.right - boundary.left - elementWidth) / 2;
      y = (boundary.bottom - boundary.top - elementHeight) / 2;
    } else if (this.options.initialPosition === 'random') {
      // 随机位置
      const elementWidth = this.element.offsetWidth;
      const elementHeight = this.element.offsetHeight;
      const maxX = Math.max(0, boundary.right - boundary.left - elementWidth);
      const maxY = Math.max(0, boundary.bottom - boundary.top - elementHeight);
      x = Math.random() * maxX;
      y = Math.random() * maxY;
    } else if (typeof this.options.initialPosition === 'object') {
      // 自定义位置
      x = this.options.initialPosition.x || 0;
      y = this.options.initialPosition.y || 0;
    } else {
      // 无效配置，保持当前位置
      this.updatePosition();
      return;
    }
    
    // 确保位置在边界内
    x = Math.max(boundary.left, Math.min(boundary.right, x));
    y = Math.max(boundary.top, Math.min(boundary.bottom, y));
    
    // 设置位置
    this.element.style.left = x + 'px';
    this.element.style.top = y + 'px';
  }
  
  updatePosition() {
    const rect = this.element.getBoundingClientRect();
    const parentRect = this.element.parentElement ? this.element.parentElement.getBoundingClientRect() : { left: 0, top: 0 };
    const relativeX = rect.left - parentRect.left;
    const relativeY = rect.top - parentRect.top;
    this.element.style.left = relativeX + 'px';
    this.element.style.top = relativeY + 'px';
  }
  
  // 设置拖拽范围
  setBoundary(boundary) {
    this.options.boundary = { ...this.options.boundary, ...boundary };
  }
  
  // 设置位置
  setPosition(x, y) {
    const boundary = this.getBoundary();
    
    // 确保位置在边界内
    const constrainedX = Math.max(boundary.left, Math.min(boundary.right, x));
    const constrainedY = Math.max(boundary.top, Math.min(boundary.bottom, y));
    
    this.element.style.left = constrainedX + 'px';
    this.element.style.top = constrainedY + 'px';
    
    return { x: constrainedX, y: constrainedY };
  }
  
  // 获取当前位置
  getPosition() {
    const rect = this.element.getBoundingClientRect();
    const parentRect = this.element.parentElement ? this.element.parentElement.getBoundingClientRect() : { left: 0, top: 0 };
    return {
      x: rect.left - parentRect.left,
      y: rect.top - parentRect.top
    };
  }
  
  // 启用/禁用拖拽
  setEnabled(enabled) {
    this.options.enabled = enabled;
    this.element.style.cursor = enabled ? 'move' : 'default';
  }
  
  // 销毁拖拽功能
  destroy() {
    this.handle.removeEventListener('mousedown', this.onMouseDown);
    document.removeEventListener('mousemove', this.onMouseMove);
    document.removeEventListener('mouseup', this.onMouseUp);
    
    this.handle.removeEventListener('touchstart', this.onTouchStart);
    document.removeEventListener('touchmove', this.onTouchMove);
    document.removeEventListener('touchend', this.onTouchEnd);
  }
}

// 导出类
if (typeof module !== 'undefined' && module.exports) {
  module.exports = DragHelper;
} else if (typeof window !== 'undefined') {
  window.DragHelper = DragHelper;
}
